package com.lzh.runke.core.handler;

import com.lzh.runke.core.web_base.enums.BaseEnum;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * Integer/String/Boolean 转 enum
 *
 * @author wanchonglang
 * @date 2022/04/09 16:10
 **/
@MappedTypes(value = BaseEnum.class)
@MappedJdbcTypes(value = {JdbcType.VARCHAR, JdbcType.INTEGER, JdbcType.BOOLEAN})
public class EnumTypeHandler<T extends BaseEnum> extends BaseTypeHandler<T> {

    private final Class<T> type;

    public EnumTypeHandler(Class<T> type) {
        if (type == null) {
            throw new IllegalArgumentException("Type argument cannot be null");
        }
        this.type = type;
    }

    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, T baseEnum, JdbcType jdbcType) throws SQLException {
        if (baseEnum.getValue() instanceof Integer) {
            preparedStatement.setInt(i, (Integer) baseEnum.getValue());
        } else if (baseEnum.getValue() instanceof String) {
            preparedStatement.setString(i, (String) baseEnum.getValue());
        } else if (baseEnum.getValue() instanceof Boolean) {
            preparedStatement.setBoolean(i, (Boolean) baseEnum.getValue());
        }
    }

    @Override
    public T getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        return convert(resultSet.getObject(columnName));
    }

    @Override
    public T getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        return convert(resultSet.getObject(columnIndex));
    }

    @Override
    public T getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        return convert(callableStatement.getObject(columnIndex));
    }

    //数字/字符串/布尔 转枚举
    private T convert(Object value) {
        if (null == value) {
            return null;
        }
        T[] enums = type.getEnumConstants();
        if (enums == null) {
            throw new IllegalArgumentException(type.getSimpleName() + " does not represent an enum type.");
        }
        for (T em : enums) {
            if (value instanceof Boolean) {
                if (em.getValue().equals(value)) {
                    return em;
                }
                if (Boolean.TRUE.equals(value)) {
                    if ("1".equals(em.getValue().toString())) {
                        return em;
                    }

                } else {
                    if ("0".equals(em.getValue().toString())) {
                        return em;
                    }
                }
            } else {
                if (em.getValue().toString().equals(value.toString())) {
                    return em;
                }
            }
        }
        return null;
    }
}
